package mrusanov.ui.battle

import actions.{ PlayerSpriteAttackAction, MomentaryActionAdapter, Action }
import javax.swing.{ JLabel, JButton, JPanel }
import mrusanov.battle.{ PlayerState, AttackInfo, Battle }
import java.awt.{ Dimension, GridLayout }
import net.miginfocom.swing.MigLayout
import mrusanov.team.Team
import mrusanov.view.PlayerSprite
import mrusanov.ui.battle.actions.TimeTakingToMomentaryAction

class BattlePanel(val battle: Battle, val userTeam: Team, parent: BattleContainerPanel) extends JPanel {
	private val QUICK_BATTLE = true

	setLayout(new MigLayout("fill"))

	var arenas: Vector[MiniArenaComponent] = Vector()
	var upUnitViews: Vector[UnitStatusViewComponent] = Vector()
	var downUnitViews: Vector[UnitStatusViewComponent] = Vector()
	var downUnitControls: Vector[UnitOrderComponent] = Vector()

	val controller = new BattleUIController(userTeam, this)

	battle.miniArenas foreach (arena => {
		val comp = new MiniArenaComponent(arena, userTeam)
		arenas :+= comp

		val hostUnitStatusView = new UnitStatusViewComponent(comp, true, false)
		val guestUnitStatusView = new UnitStatusViewComponent(comp, false, true)

		if (userTeam == battle.hostTeam) {
			upUnitViews :+= guestUnitStatusView
			downUnitViews :+= hostUnitStatusView
		} else {
			upUnitViews :+= hostUnitStatusView
			downUnitViews :+= guestUnitStatusView
		}

		val unitControl = new UnitOrderComponent(controller, comp)
		downUnitControls :+= unitControl
	})
	upUnitViews.zipWithIndex.foreach(vi => add(vi._1, "cell " + vi._2 + " 1, h 20%!"))
	arenas.zipWithIndex.foreach(vi => add(vi._1, "cell " + vi._2 + " 2 1 2, w 8.5%!, h 30%!"))

	downUnitViews.zipWithIndex.foreach(vi => add(vi._1, "cell " + vi._2 + " 4, h 20%!"))
	downUnitControls.zipWithIndex.foreach(vi => add(vi._1, "cell " + vi._2 + " 5, w 8.5%!, h 20%!"))

	refresh()
	ActionsExecutor.startTimer()

	def refresh() {
		downUnitControls foreach (_.refresh())
		downUnitViews foreach (_.refresh())
		upUnitViews foreach (_.refresh())
		arenas foreach (_.refresh())
	}

	def turnOver(attacks: List[AttackInfo]) {
		controller.turnOver()
		ActionsExecutor.addActions(transformAttackInfoToActions(attacks))
	}

	private def transformAttackInfoToActions(attacks: List[AttackInfo]): List[Action] = {
		val attackActions = attacks.flatMap(transformAttackInfo)
		attackActions ++ turnEndingActions
	}

	private def transformAttackInfo(info: AttackInfo): List[Action] = {
		val defenderDied = !info.defender.alive
		val arena = getArena(info.attacker)
		val attackerView = arena.playerSpriteView(info.attacker)
		if (attackerView.isEmpty) {
			throw new IllegalStateException("attackerView cann't be empty!")
		}
		val defenderView = arena.playerSpriteView(info.defender)
		if (defenderView.isEmpty) {
			throw new IllegalStateException("defenderView cann't be empty!")
		}

		val defender = defenderView.get
		val attacker = attackerView.get

		val attackAnimation = new PlayerSpriteAttackAction(arena, attacker, defender, info.successful, defenderDied)

		if (QUICK_BATTLE) {
			List(new TimeTakingToMomentaryAction(attackAnimation))
		} else {
			List(attackAnimation)
		}
	}

	private def getArena(state: PlayerState): MiniArenaComponent = {
		arenas.find(_.playerSpriteView(state).isDefined).get
	}

	private def turnEndingActions: List[Action] = {
		new MomentaryActionAdapter {
			def execute() {
				parent.refreshRightPanel()
				refresh()
			}
		} :: Nil
	}

	setPreferredSize(new Dimension(13 * 72, 600))
}
